package cn.dkk.Spring.framework.context.support;

import cn.dkk.Spring.framework.beans.BeanDefinition;
import cn.dkk.Spring.framework.beans.MutablePropertyValues;
import cn.dkk.Spring.framework.beans.PropertyValue;
import cn.dkk.Spring.framework.beans.factory.support.xml.XmlBeanDefinitionReader;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * @author dkk
 * @date 2022/8/4
 * @desc ioc容器具体的子实现类,用于加载类路径下xml格式的配置文件
 */
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{

    public ClassPathXmlApplicationContext(String configLocation){
        this.configLocation=configLocation;
        beanDefinitionReader = new XmlBeanDefinitionReader();
        try {
            this.refresh();
        }catch (Exception e){

        }
    }

    @Override
    public Object getBean(String name) throws Exception {
        Object o = singletonObjects.get(name);
        if (o!=null){
            return o;
        }
        BeanDefinition beanDefinition = beanDefinitionReader.getRegistry().getBeanDefinition(name);
        String className = beanDefinition.getClassName();
        Class<?> aClass = Class.forName(className);
        // 实例化bean对象
        Object beanObj = aClass.newInstance();
        //依赖注入
        MutablePropertyValues mutablePropertyValues = beanDefinition.getMutablePropertyValues();
        PropertyValue[] propertyValues = mutablePropertyValues.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues) {
            String value = propertyValue.getValue();
            String ref = propertyValue.getRef();
            // ref为引用对象
            if (ref!=null&&!ref.equals("")){
                Object bean = getBean(ref);
                String capitalize = StringUtils.capitalize(ref)+"set";
                for (Method method : aClass.getMethods()) {
                    if (method.getName().equals(capitalize)){
                        method.invoke(beanObj,bean);
                    }
                }
            }
            // value为直接引用value属性中的值
            if (value!=null&&value.equals("")){
                String capitalize = StringUtils.capitalize(value)+"set";
                for (Method method : aClass.getMethods()) {
                    if (method.getName().equals(capitalize)){
                        method.invoke(beanObj,value);
                    }
                }
            }
        }
        singletonObjects.put(name,beanObj);
        return beanObj;
    }

    @Override
    public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {
        Object bean = getBean(name);
        if (bean==null){
            return null;
        }else {
            return clazz.cast(bean);
        }
    }
}
